/*
 * author: Andriamananony, Meß, Falk
 */

package plan;

import java.util.ArrayList;
import java.util.HashMap;

import util.Interval;
import auftrag.Auftrag;
import auftrag.Operation;
import auftrag.Ressource;

public class Plan implements Cloneable {
	private ArrayList<Belegung> mBelegungen = new ArrayList<Belegung>();
	private HashMap<Operation, Interval> mPlannedOperations = new HashMap<Operation, Interval>();
	private int quality = -1;
	/**
	 * Fügt dem Plan eine neue Belegung hinzu
	 * @param b Belegung, die hinzugefügt werden soll
	 * @return true, falls die Belegung erfolgreich hinzugefügt werden konnte
	 */
	public boolean addBelegung(Belegung b){
		mPlannedOperations.put(b.getOperation(), b.getInterval());
		mBelegungen.add(b);
		b.getOperation().setIntervall(b.getInterval());
		b.getResource().addInterval(b.getInterval());
		
		return true;
	}
	
	public void print(){
		HashMap<Auftrag, Integer> orderID = new HashMap<Auftrag, Integer>();
		System.out.println("[");
		int nOrderID = 0;
		for(Belegung b: mBelegungen){
			System.out.println("{'resource':'"+b.getResource()+"',");
			System.out.println("'start':"+b.getInterval().getStart()+",");
			System.out.println("'duration':"+b.getInterval().getDuration()+",");
			System.out.println("'orderid':"+b.getAuftrag()+",");
			if(orderID.containsKey(b.getAuftrag())){
				nOrderID = orderID.get(b.getAuftrag())+1;
				orderID.put(b.getAuftrag(), nOrderID);
			} else {
				orderID.put(b.getAuftrag(), 1);
				nOrderID = 1;
			}
			System.out.println("'index_in_order':"+nOrderID+"},");
		}
		System.out.println("]");
	}
	
	public boolean isPlanned(Operation o){
		if(o!= null && mPlannedOperations.containsKey(o))
			return true;
		return false;
	}
	
	public ArrayList<Operation> getOperations(){
		ArrayList<Operation> tmp = new ArrayList<Operation>();
		tmp.addAll(mPlannedOperations.keySet());
		return tmp;
	}
	
	public ArrayList<Belegung> getBelegungen(){
		return mBelegungen;
	}
	
	public int getEndDate(){
		int max = 0;
		for(Belegung b:mBelegungen)
			if(b.getInterval().getEnd() > max)
				max = b.getInterval().getEnd();
		return max;
	}
	
	public int getQuality(boolean newCalculation){
		if(newCalculation || quality == -1){
			quality = 0;
			ArrayList<Auftrag> auftrList = new ArrayList<Auftrag>();
			for (Belegung b : mBelegungen) {
				Operation o = b.getOperation();
				if(!auftrList.contains(o.getParent().getParent().getParent()))
					auftrList.add(o.getParent().getParent().getParent());
			}
		
		
			for(Auftrag a : auftrList){
				int delay = Math.max(a.getEndDate() - a.getDeadline(), 0);
				quality += delay * a.getPriority();
			}
		}
		return quality;
	}
	
	public Operation getLastOperation(Ressource r){
		for(int i = mBelegungen.size()-1; i > 0; i--){
			if(mBelegungen.get(i).getResource().equals(r))
				return mBelegungen.get(i).getOperation();
		}
		return null;
	}
}
